import os, uuid
from flask import current_app
from werkzeug.utils import secure_filename
from PIL import Image
from slugify import slugify as _slugify


ALLOWED = {'.jpg', '.jpeg', '.png', '.webp'}

def to_bool(val):
    """把各种可能的表单值统一转换成布尔值"""
    if isinstance(val, bool):
        return val
    if val is None:
        return False
    s = str(val).lower()
    return s in ('1', 'true', 'yes', 'y', 'on')


# app/utils/jinja_filters.py（示例）
def to_static(path: str) -> str:
    if not path:
        return ''
    if path.startswith('http'):
        return path
    if path.startswith('/static/'):
        return path
    return '/static/' + path.lstrip('/')


# 记得顶部确保有：
# from PIL import Image
# import os, uuid
# from werkzeug.utils import secure_filename
# from flask import current_app
def save_image(file_storage, subdir='', max_size=(1200, 1200), jpeg_quality=75, min_kb=200):
    """
    保存并自动压缩图片：
    - 只允许 ALLOWED 后缀
    - 生成 uuid 文件名
    - 限制最大宽高 max_size
    - JPEG 降质到 jpeg_quality
    - 小于 min_kb 的图片不压缩（避免反复重写）
    返回值：以 /static 为基准的相对 URL（前面带 /）
    """
    if not file_storage:
        return None

    filename = secure_filename(file_storage.filename)
    ext = os.path.splitext(filename)[1].lower()
    if ext not in ALLOWED:
        raise ValueError('不支持的图片格式')

    # 统一文件名
    new_name = f"{uuid.uuid4().hex}{ext}"
    upload_dir = os.path.join(current_app.config['UPLOAD_FOLDER'], subdir)
    os.makedirs(upload_dir, exist_ok=True)
    dest = os.path.join(upload_dir, new_name)

    # 先原样保存
    file_storage.save(dest)

    # 小图不压缩，避免重复 IO
    try:
        size_kb = os.path.getsize(dest) / 1024
    except OSError:
        size_kb = 0

    try:
        img = Image.open(dest)
    except Exception:
        # 不是图片或损坏，直接返回原图路径
        rel = os.path.relpath(dest, os.path.join(current_app.root_path, 'static'))
        return '/' + rel.replace('\\', '/')

    # 仅对较大的图片做压缩/缩放
    if size_kb >= min_kb:
        try:
            # 限制最大宽高
            orig_w, orig_h = img.size
            max_w, max_h = max_size
            if orig_w > max_w or orig_h > max_h:
                img.thumbnail(max_size, Image.Resampling.LANCZOS)

            # 统一模式，JPEG 不支持透明
            if img.mode in ("RGBA", "P"):
                img = img.convert("RGB")

            # 按扩展名选择保存格式
            if ext in ('.jpg', '.jpeg'):
                img.save(dest, format='JPEG', optimize=True, quality=jpeg_quality)
            elif ext == '.png':
                # PNG: 保留格式，但做优化
                img.save(dest, format='PNG', optimize=True)
            else:
                # 其它格式：直接覆写为 JPEG
                new_dest = os.path.splitext(dest)[0] + '.jpg'
                img.save(new_dest, format='JPEG', optimize=True, quality=jpeg_quality)
                # 替换路径指向新的 jpg 文件
                dest = new_dest

        except Exception:
            # 压缩失败就保持原文件，不影响上传
            pass

    # 返回相对路径供模板使用（以 /static 为基准）
    rel = os.path.relpath(dest, os.path.join(current_app.root_path, 'static'))
    return '/' + rel.replace('\\', '/')



def canonical_slug(name: str) -> str:
    # 统一：小写、连字符、ASCII
    return _slugify(name or "", lowercase=True, separator='-')